/*
 * Copyright 2008 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.sepia.data.db;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import edu.cmu.lti.sepia.infra.system.model.User;
import edu.cmu.lti.sepia.util.ServletUtil;

/**
 * 
 * Manages User object in a DB.
 * 
 * @see User
 * @author Hideki Shima
 *
 */
public class UserDAO {
	
	public static List<User> getUsers( SQL sql ) throws SQLException {
		String query = Query.generate( Query.GET_USERS, "" );
		PreparedStatement ps = sql.getConnection().prepareStatement(query);
		ResultSet rs = null;
		List<User> users = new ArrayList<User>();
		
		rs = sql.executeSelect(ps);
		if ( rs == null ) System.out.println( ps );
		while ( rs.next() ) users.add( rsToObject(rs) );

		rs.close();
		ps.close();

		return users;
	}
	
	 public static Map<Integer,User> getUsersInMap( SQL sql ) throws SQLException {
	    List<User> users = getUsers(sql);
	    if(users==null)return null;
	    Map<Integer,User> map = new LinkedHashMap<Integer,User>(users.size());
	    for ( User u : users ) {
	      map.put(u.getUserId(), u);
	    }
	    return map;
	  }
	
	public static void updateUser( SQL sql, User user ) throws SQLException {
		String query = Query.generate( Query.UPDATE_USER, "" );
		
		PreparedStatement ps = sql.getConnection().prepareStatement(query);
		ps.setString(1, user.getUserName());
		ps.setString(2, user.getPassword());
		ps.setString(3, user.getRole());
		ps.setString(4, user.getDisplayLang());
		ps.setString(5, user.getDescription());
		ps.setInt(6, user.getUserId());
		sql.execute(ps);
		ps.close();
	}
	
	public static void updateUserWithoutPassword( SQL sql, User user ) throws SQLException {
	  String query = Query.generate( Query.UPDATE_USER2, "" );
	  PreparedStatement ps = sql.getConnection().prepareStatement(query);
	  ps.setString(1, user.getUserName());
	  ps.setString(2, user.getRole());
	  ps.setString(3, user.getDisplayLang());
	  ps.setString(4, user.getDescription());
	  ps.setInt(5, user.getUserId());
	  sql.execute(ps);
	  ps.close();
	}
	
	public static String addUser( SQL sql, User user ) throws SQLException {
		String query = Query.generate( Query.ADD_USER, "" );
		
		PreparedStatement ps = sql.getConnection().prepareStatement(query);
		
		ps.setString(1, user.getUserName());
		ps.setString(2, user.getPassword());
		ps.setString(3, user.getRole());
		ps.setString(4, user.getDisplayLang());
		ps.setString(5, user.getDescription());
		String message = "Executing: "+ps.toString().replaceAll(".+: ", "")+"\n";
		message += sql.executeInSilence(ps);
		ps.close();
		return message;
	}

	public static void deleteUser( SQL sql, int userId ) throws SQLException {
		String query = Query.generate( Query.DELETE_USER, "" );
		
		PreparedStatement ps = sql.getConnection().prepareStatement(query);
		
		ps.setInt(1, userId);
		sql.execute(ps);
		ps.close();
	}
	
	public static User findByUserName( SQL sql, String userName ) throws SQLException {
		String query = Query.generate( Query.FIND_USER, "" );
		PreparedStatement ps = sql.getConnection().prepareStatement(query);
		ResultSet rs = null;
		
		User user = null;
		ps.setString(1, userName);
		rs = sql.executeSelect(ps);
		if ( rs.next() ) {
			user = rsToObject(rs);
		}
		rs.close();
		ps.close();
		
		return user;
	}
	
  public static User findLatest(SQL sql) throws SQLException {
    String query = Query.generate(Query.FIND_LATEST_USER, "");

    PreparedStatement ps = sql.getConnection().prepareStatement(query);
    ResultSet rs = null;
    User user = null;

    rs = sql.executeSelect(ps);
    if (rs.next()) {
      user = rsToObject(rs);
    }
    rs.close();
    ps.close();

    return user;
  }
	
	public static void updateDisplayLang(SQL sql, int userId, String displayLang) 
	throws SQLException{
	  String query = Query.generate( Query.UPDATE_DISPLAY_LANG, "" );
    
    PreparedStatement ps = sql.getConnection().prepareStatement(query);
    ps.setString(1, displayLang);
    ps.setInt(2, userId);
    sql.execute(ps);
    ps.close();
	}
	
	private static User rsToObject( ResultSet rs ) throws SQLException {
		User user = new User( rs.getInt(1), rs.getString(2), 
				rs.getString(3), rs.getString(4),
				rs.getString(5), rs.getString(6) );
		return user;
	}
	
  public static JSONObject convertUser( User user ) throws JSONException {
    JSONObject json = new JSONObject();
    JSONArray jsonArray = new JSONArray();
    JSONObject j = new JSONObject();
    j.put("userId", user.getUserId());
    j.put("userName", user.getUserName());
    j.put("password", user.getPassword());
    j.put("role", user.getRole());
    j.put("displayLang", user.getDisplayLang());
    j.put("description", user.getDescription());
    jsonArray.put(j);
    json.put("users", jsonArray);
    return json;
  }
  
  public static JSONObject convertUsers( List<User> users ) throws JSONException {
    JSONObject json = new JSONObject();
    JSONArray jsonArray = new JSONArray();
    for ( User u : users ) {
      JSONObject j = new JSONObject();
      j.put("userId", u.getUserId());
      j.put("userName", u.getUserName());
      jsonArray.put(j);
    }
    json.put("users", jsonArray);
    return json;
  }
  
  public static User parseRequest( HttpServletRequest request ) {
    //if ( request.getParameter("serName")==null ) return null;
    
    ServletUtil s = new ServletUtil( request );
    
    return new User( 
        s.readInt("userId", 0),
        s.readString("userName", ""),
        s.readString("password", ""),
        s.readString("role", ""),
        s.readString("displayLang", ""),
        s.readString("description", "")
    );
  }
    
}
